<template>
  <view class="container">
    <view>
      <video id="localVideo" autoplay playsinline></video>
      <video id="remoteVideo" autoplay playsinline></video>
    </view>
    <view>
      <button @click="handleStart">start</button>
    </view>
    <view>
      <input v-model="targetId" type="text">
      <button @click="handleCall">call</button>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      localStream: null,
      socket: null,
      targetId: '',
      pc: null,
      currentUserId: null,
    };
  },
  onLoad() {
    const params = this.$route.query;
    this.currentUserId = params.id;
    this.initWebsocket();
  },
  methods: {
    async handleStart() {
      try {
        this.localStream = await uni.getUserMedia({ video: true, audio: true });
        const localVideo = uni.createVideoContext('localVideo');
        localVideo.srcObject = this.localStream;
      } catch (e) {
        console.error('获取媒体流失败', e);
      }
    },
    initWebsocket() {
      this.socket = new WebSocket(`wss://192.168.2.10:8080?id=${this.currentUserId}`);
      this.socket.onopen = () => {
        console.log('WebSocket连接成功');
      };
      this.socket.onmessage = (e) => {
        const message = JSON.parse(e.data);
        switch (message.code) {
          case 'connect_success':
            console.log('连接成功');
            break;
          case 'offer':
            this.getOffer(message.data);
            break;
          case 'answer':
            this.getAnswer(message.data);
            break;
          case 'icecandidate':
            this.pc.addIceCandidate(new RTCIceCandidate(message.data.candidate));
            break;
          default:
            console.log('收到未知消息');
        }
      };
      this.socket.onerror = (e) => {
        console.error('WebSocket错误', e);
      };
      this.socket.onclose = () => {
        console.log('WebSocket连接关闭');
      };
    },
    handleCall() {
      this.pc = new RTCPeerConnection({});
      this.localStream.getTracks().forEach((track) => {
        this.pc.addTrack(track, this.localStream);
      });
      this.pc.ontrack = (event) => {
        const remoteVideo = uni.createVideoContext('remoteVideo');
        remoteVideo.srcObject = event.streams[0];
      };
      this.pc.onicecandidate = (event) => {
        if (event.candidate) {
          this.socket.send(JSON.stringify({
            code: 'icecandidate',
            data: {
              targetId: this.targetId,
              candidate: event.candidate,
            },
          }));
        }
      };
      this.sendOffer();
    },
    async sendOffer() {
      const offer = await this.pc.createOffer();
      await this.pc.setLocalDescription(offer);
      this.socket.send(JSON.stringify({
        code: 'offer',
        data: {
          targetId: this.targetId,
          offer: offer,
        },
      }));
    },
    getAnswer(answer) {
      this.pc.setRemoteDescription(new RTCSessionDescription(answer));
    },
    getOffer(offer) {
      this.pc = new RTCPeerConnection({});
      this.localStream.getTracks().forEach((track) => {
        this.pc.addTrack(track, this.localStream);
      });
      this.pc.ontrack = (event) => {
        const remoteVideo = uni.createVideoContext('remoteVideo');
        remoteVideo.srcObject = event.streams[0];
      };
      this.pc.onicecandidate = (event) => {
        if (event.candidate) {
          this.socket.send(JSON.stringify({
            code: 'icecandidate',
            data: {
              targetId: offer.fromId,
              candidate: event.candidate,
            },
          }));
        }
      };
      this.pc.setRemoteDescription(new RTCSessionDescription(offer));
      this.sendAnswer(offer.fromId);
    },
    async sendAnswer(targetId) {
      const answer = await this.pc.createAnswer();
      await this.pc.setLocalDescription(answer);
      this.socket.send(JSON.stringify({
        code: 'answer',
        data: {
          targetId: targetId,
          answer: answer,
        },
      }));
    },
  },
};
</script>

<style scoped>
video {
  width: 500px;
  height: 400px;
  border: 1px dashed black;
}
</style>
